﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cherry.Agile.Core;
using System.ServiceModel;
using Cherry.Agile.Distributed.Queue;

namespace Cherry.Agile.Distributed.Queue
{
    /// <summary>
    /// 队列
    /// </summary>
    public sealed class Queuer
    {
        static IQueueHandler _handler;
        static object _sync = new object();

        static Queuer()
        {
           
        }

        static IQueueHandler Handler
        {
            get
            {
                var channel = _handler as IClientChannel;
                if (channel == null || channel.State == CommunicationState.Faulted)
                {
                    lock (_sync)
                    {
                        if (channel == null || channel.State == CommunicationState.Faulted)
                            _handler = new System.ServiceModel.ChannelFactory<IQueueHandler>("queue").CreateChannel();
                    }
                }
                return _handler;
                
            }
        }
        /// <summary>
        /// 获取队列中未读消息
        /// </summary>
        /// <param name="queueName">队列名称</param>
        /// <param name="index">返回当前消息的位置</param>
        /// <returns></returns>
        static public string Get(string queueName,out int index)
        {

            return Handler.Get(queueName,out index);
        }

        /// <summary>
        /// 获取队列中未读消息
        /// </summary>
        /// <param name="queueName">队列名称</param>
        /// <returns></returns>
        static public string Get(string queueName)
        {
            var index = 0;
            return Get(queueName, out index);
        }

        /// <summary>
        /// 查看指定位置队列中的消息
        /// </summary>
        /// <param name="queueName">队列名称</param>
        /// <param name="index">位置</param>
        /// <returns></returns>
        public static string View(string queueName, int index)
        {
            return Handler.View(queueName, index);
        }

        /// <summary>
        /// 写入消息
        /// </summary>
        /// <param name="queueName">队列名称</param>
        /// <param name="data">消息内容</param>
        /// <returns></returns>
        public static int Set(string queueName, string data)
        {
            return Handler.Set(queueName, data);
        }

        /// <summary>
        /// 异步写入消息
        /// </summary>
        /// <param name="queueName">队列名称</param>
        /// <param name="data">消息内容</param>
        /// <param name="callBack">写入成功的回调函数</param>
        /// <param name="error">写入失败的回调函数</param>
        public static void AsyncSet(string queueName, string data, Action<int> callBack, Action<string> error = null)
        {
            var action = new Func<int>(() =>
                {
                    return Handler.Set(queueName, data);
                });

            action.BeginInvoke((ai) =>
                {
                    try
                    {
                        var a = ai.AsyncState as Func<int>;
                        var index = a.EndInvoke(ai);
                        if (callBack != null)
                            callBack(index);
                    }
                    catch (Exception ex)
                    {
                        if (error != null)
                            error(ex.Message);
                    }
                }, action);
        }

        /// <summary>
        /// 异步写入消息
        /// </summary>
        /// <typeparam name="T">消息类型</typeparam>
        /// <param name="queueName">队列名称</param>
        /// <param name="data">消息</param>
        /// <returns></returns>
        public static int Set<T>(string queueName, T data)
        {
            if (data == null)
                return -1;
            var temp = Newtonsoft.Json.JsonConvert.SerializeObject(data);
            return Set(queueName, temp);
        }

        /// <summary>
        /// 异步写入消息
        /// </summary>
        /// <typeparam name="T">消息类型</typeparam>
        /// <param name="queueName">队列名称</param>
        /// <param name="data">消息内容</param>
        /// <param name="callBack">写入成功的回调函数</param>
        /// <param name="error">写入失败的回调函数</param>
        /// <example>
        /// <code>
        ///  const string UserLoginQueue = "UserLogin";
        ///  Cherry.Agile.Distributed.Queue.Queuer.AsyncSet&lt;Enterprise.Entity.LoginLog&gt;(UserLoginQueue, loginLog, null);
        /// </code>
        /// </example>
        public static void AsyncSet<T>(string queueName, T data, Action<int> callBack, Action<string> error = null)
        {
            var action = new Func<int>(() =>
            {
                var temp = Newtonsoft.Json.JsonConvert.SerializeObject(data);
                return Handler.Set(queueName, temp);
            });

            action.BeginInvoke((ai) =>
            {
                var a = ai.AsyncState as Func<int>;

                try
                {
                    var index = a.EndInvoke(ai);
                    if (callBack != null)
                        callBack(index);
                }
                catch (Exception ex)
                {
                    if (error != null)
                        error(ex.Message);
                }


            }, action);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queueName"></param>
        /// <returns></returns>
        static public T Get<T>(string queueName)
        {
            var val = Get(queueName);
            if (string.IsNullOrEmpty(val))
                return default(T);

            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(val);
        }

        /// <summary>
        /// 获取队列信息指定位置内容
        /// </summary>
        /// <typeparam name="T">内容类型</typeparam>
        /// <param name="queueName">队列名称</param>
        /// <param name="index">索引位置</param>
        /// <returns>获取的数据</returns>
        public static T View<T>(string queueName, int index)
        {
            var val = View(queueName, index);
            if (string.IsNullOrEmpty(val))
                return default(T);

            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(val);
        }

        /// <summary>
        /// 配置队列
        /// </summary>
        /// <param name="queueName"></param>
        /// <param name="config"></param>
        /// <returns></returns>
        public static string Config(string queueName, string config)
        {
            return Handler.Config(queueName, config);
        }

        /// <summary>
        /// 队列状态
        /// </summary>
        /// <param name="queueName"></param>
        /// <returns></returns>
        public static string Status(string queueName)
        {
            return Handler.Status(queueName);
        }
    }
}
